//@ts-ignore
import * as mqtt from "mqtt/dist/mqtt.min.js";
import { getWebMqttInfoApi, MqttConnectOption } from "@/api/qcpublic/qcpublic";

/**
 * 网站消息结构接口
 */
export interface WebsiteMessage {
  /** 设备编号【逗号分隔多个】 */
  deviceNos: string;
  /** 部门id */
  deptId: number;
  /** 创建时间 */
  createdAt?: string;
  /** 大类型 */
  bigType: string;
  /** 类型 */
  type: string;
  /** 值 */
  value: string;
  /** 状态 */
  status: number;
}

export const getWebTopic = (deptId:number) =>{
  return "qciot/ae/v2/webSub/"+ deptId.toString();
}

let mqttConfig : MqttConnectOption | null = null;

// MQTT客户端实例
let mqttClient: mqtt.MqttClient | null = null;

// 已订阅的Topic集合，用于避免重复订阅
const subscribedTopics: Set<string> = new Set();

/**
 * 连接MQTT服务器
 * @returns Promise<mqtt.MqttClient>
 */
export const connectMqtt = async (): Promise<mqtt.MqttClient> => {
  // 如果已经有连接实例，直接返回
  if (mqttClient && mqttClient.connected) {
    return mqttClient;
  }

  try {
    if(!mqttClient) {
      // 获取MQTT连接信息
      const response = await getWebMqttInfoApi();
      mqttConfig = response.data?.info;
    }
    if (!mqttConfig) {
      throw new Error('获取MQTT配置失败');
    }

    // Base64解码用户名和密码
    const decodeUser = (encoded: string): string => {
      try {
        return atob(encoded);
      } catch (error) {
        console.error('解码失败:', error);
        return encoded;
      }
    };

    const user = decodeUser(mqttConfig.user || '');
    const password = decodeUser(mqttConfig.password || '');

    // 构建MQTT连接URL
    const protocol = mqttConfig.protocol=="https" ? 'wss':"ws"; // 使用WebSocket协议
    const host = mqttConfig.publicHost;
    const port = mqttConfig.websocketPort || 8083;
    const brokerUrl = `${protocol}://${host}:${port}/mqtt`;

    // 连接选项
    const options: mqtt.IClientOptions = {
      username: user,
      password: password,
      clientId: mqttConfig.clientId || `webmqtt_${Math.random().toString(16).substr(2, 8)}`,
      clean: true,
      connectTimeout: 4000,
      reconnectPeriod: 20000,
      keepalive: 60,
    };

    // 创建MQTT客户端连接
    mqttClient = mqtt.connect(brokerUrl, options);

    // 监听连接事件
    mqttClient.on('connect', () => {
      console.log('MQTT连接成功');
    });

    mqttClient.on('error', (error) => {
      console.error('MQTT连接错误:', error);
    });

    mqttClient.on('reconnect', () => {
      console.log('MQTT尝试重连...');
    });

    mqttClient.on('close', () => {
      console.log('MQTT连接关闭');
    });

    return mqttClient;
  } catch (error) {
    console.error('连接MQTT失败:', error);
    throw error;
  }
};

/**
 * 订阅Topic
 * @param topic 订阅的主题
 * @param messageHandler 消息处理回调函数
 * @param options 订阅选项
 * @returns Promise<boolean>
 */
export const subscribeTopic = async (
  topic: string,
  messageHandler?: (topic: string, message: Buffer, packet: any) => void,
  options?: object
): Promise<boolean> => {
  // 检查是否已经订阅过该主题
  if (subscribedTopics.has(topic)) {
    console.log(`主题 ${topic} 已经订阅过，无需重复订阅`);
    return true;
  }

  try {
    if (!mqttClient || !mqttClient.connected) {
      mqttClient = await connectMqtt();
    }

    return new Promise((resolve, reject) => {
      // @ts-ignore
      mqttClient!.subscribe(topic, options || {}, (error) => {
        if (error) {
          console.error(`订阅主题 ${topic} 失败:`, error);
          reject(error);
        } else {
          // 添加到已订阅集合
          subscribedTopics.add(topic);
          console.log(`成功订阅主题: ${topic}`);

          // 如果提供了消息处理回调函数，为该主题添加消息事件监听器
          if (messageHandler && mqttClient) {
            // 创建闭包函数，只处理当前主题的消息
            const topicSpecificHandler = (receivedTopic: string, message: Buffer, packet: any) => {
              if (receivedTopic === topic) {
                messageHandler(receivedTopic, message, packet);
              }
            };

            // 添加消息事件监听器
            mqttClient.on('message', topicSpecificHandler);

            // 保存处理函数的引用，以便取消订阅时移除监听器
            (mqttClient as any)._topicHandlers = (mqttClient as any)._topicHandlers || new Map();
            (mqttClient as any)._topicHandlers.set(topic, topicSpecificHandler);
          }

          resolve(true);
        }
      });
    });
  } catch (error) {
    console.error('订阅Topic失败:', error);
    return false;
  }
};

/**
 * 取消订阅Topic
 * @param topic 要取消订阅的主题
 * @returns Promise<boolean>
 */
export const unsubscribeTopic = async (topic: string): Promise<boolean> => {
  // 检查是否已经订阅过该主题
  if (!subscribedTopics.has(topic)) {
    console.log(`主题 ${topic} 未订阅，无需取消订阅`);
    return true;
  }

  try {
    // 移除消息事件监听器
    if (mqttClient && (mqttClient as any)._topicHandlers && (mqttClient as any)._topicHandlers.has(topic)) {
      const handler = (mqttClient as any)._topicHandlers.get(topic);
      mqttClient.removeListener('message', handler);
      (mqttClient as any)._topicHandlers.delete(topic);
      console.log(`已移除主题 ${topic} 的消息监听器`);
    }

    if (!mqttClient || !mqttClient.connected) {
      console.warn('MQTT未连接，无法执行取消订阅操作');
      // 从记录中移除
      subscribedTopics.delete(topic);
      return false;
    }

    return new Promise((resolve, reject) => {
      mqttClient!.unsubscribe(topic, {}, (error) => {
        if (error) {
          console.error(`取消订阅主题 ${topic} 失败:`, error);
          reject(error);
        } else {
          // 从已订阅集合中移除
          subscribedTopics.delete(topic);
          console.log(`成功取消订阅主题: ${topic}`);
          resolve(true);
        }
      });
    });
  } catch (error) {
    console.error('取消订阅Topic失败:', error);
    return false;
  }
};

/**
 * 获取所有已订阅的Topic
 * @returns string[] 已订阅的主题列表
 */
export const getSubscribedTopics = (): string[] => {
  return Array.from(subscribedTopics);
};

/**
 * 取消所有订阅
 * @returns Promise<boolean> 是否成功取消所有订阅
 */
export const unsubscribeAllTopics = async (): Promise<boolean> => {
  try {
    // 移除所有消息事件监听器
    if (mqttClient && (mqttClient as any)._topicHandlers) {
      (mqttClient as any)._topicHandlers.forEach((handler: any, topic: string) => {
        mqttClient!.removeListener('message', handler);
        console.log(`已移除主题 ${topic} 的消息监听器`);
      });
      (mqttClient as any)._topicHandlers.clear();
    }

    if (!mqttClient || !mqttClient.connected) {
      console.warn('MQTT未连接，无法取消所有订阅');
      subscribedTopics.clear();
      return false;
    }

    const topics = Array.from(subscribedTopics);
    if (topics.length === 0) {
      console.log('没有已订阅的主题');
      return true;
    }

    return new Promise((resolve, reject) => {
      mqttClient!.unsubscribe(topics, {}, (error) => {
        if (error) {
          console.error('取消所有订阅失败:', error);
          reject(error);
        } else {
          subscribedTopics.clear();
          console.log(`成功取消所有 ${topics.length} 个主题的订阅`);
          resolve(true);
        }
      });
    });
  } catch (error) {
    console.error('取消所有订阅失败:', error);
    return false;
  }
};

/**
 * 销毁MQTT连接实例
 */
export const destroyMqttConnection = (): void => {
  if (mqttClient) {
    try {
      // 移除所有消息事件监听器
      if ((mqttClient as any)._topicHandlers) {
        (mqttClient as any)._topicHandlers.clear();
      }

      mqttClient.end(true); // 强制关闭连接
      console.log('MQTT连接已销毁');
    } catch (error) {
      console.error('销毁MQTT连接失败:', error);
    } finally {
      mqttClient = null;
      // 清空已订阅主题记录
      subscribedTopics.clear();
      console.log('已清空所有主题订阅记录');
    }
  }
};

/**
 * 获取当前MQTT连接状态
 * @returns boolean
 */
export const isMqttConnected = (): boolean => {
  return mqttClient !== null && mqttClient.connected;
};

/**
 * 发送MQTT消息
 * @param topic 消息主题
 * @param message 消息内容
 * @param options 发布选项
 * @returns Promise<boolean>
 */
export const publishMessage = async (
  topic: string,
  message: string | Buffer,
  options?: object
): Promise<boolean> => {
  try {
    if (!mqttClient || !mqttClient.connected) {
      mqttClient = await connectMqtt();
    }

    return new Promise((resolve, reject) => {
      // @ts-ignore
      mqttClient!.publish(topic, message, options || {}, (error) => {
        if (error) {
          console.error(`发布消息到主题 ${topic} 失败:`, error);
          reject(error);
        } else {
          console.log(`成功发布消息到主题: ${topic}`);
          resolve(true);
        }
      });
    });
  } catch (error) {
    console.error('发布消息失败:', error);
    return false;
  }
};
